using System;
using System.IO;
using lucere.analysis.index;
using lucere.analysis.query;
using lucere.analysis.query.filter;
using lucere.entity;
using lucere.exception;
using lucere.index.read;
using lucere.service.search.collect;

namespace lucere.service.search
{
	/// <summary>
	/// The interface for search implementations.
	/// <p>
	/// Searchable is the abstract network protocol for searching. Implementations
	/// provide search over a single index, over multiple indices, and over indices
	/// on remote servers.
	/// </p>
	/// Queries, filters and sort criteria are designed to be compact so that they
	/// may be efficiently passed to a remote index, with only the top-scoring hits
	/// being returned, rather than every matching hit.
	/// 
	/// <b>NOTE:</b> this interface is kept public for convenience. Since it is not
	/// expected to be implemented directly, it may be changed unexpectedly between
	/// releases.
	/// </summary>
	public interface ISearchable : IDisposable
	{
		///<summary>
		///Lower-level search API.
		///<p>
		///<see cref="ICollector.Collect(int)"></see> is called for every document. <br/>
		///Collector-based access to remote indexes is discouraged.
		///</p>
		///Applications should only use this if they need <i>all</i> of the matching
		///documents. The high-level search API (<see cref="ISearcher.Search(IQuery,int)"></see>) is
		///usually more efficient, as it skips non-high-scoring hits.
		/// </summary>
		/// <param name="weight">to match documents</param>
		/// <param name="filter">if non-null, used to permit documents to be collected.</param>
		///<param name="collector">to receive hits</param>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		void Search(IWeight weight, IFilter filter, ICollector collector);

		///<summary>
		/// Frees resources associated with this Searcher.
		/// Be careful not to call this method while you are still using objects
		/// that reference this Searchable.
		///</summary>
		void Close();

		///<summary>
		/// <see cref="IIndexReader.DocFreq(ITerm)"></see>
		///</summary>
		int DocFreq(ITerm term);

		///<summary>
		/// Expert: For each term in the terms array, calculates the number of
		/// documents containing <code>term</code>. Returns an array with these
		/// document frequencies. Used to minimize number of remote calls.
		///</summary>
		int[] DocFreqs(ITerm[] terms);

		///<summary>
		/// Expert: Returns one greater than the largest possible document number.
		/// <see cref="IIndexReader.MaxDoc()"></see>
		///</summary>
		int MaxDoc();

		///<summary>
		/// Expert: Low-level search implementation.  Finds the top <code>n</code>
		/// hits for <code>query</code>, applying <code>filter</code> if non-null.
		///
		/// Applications should usually call <see cref="ISearcher.Search(IQuery,int)"></see> or
		/// <see cref="ISearcher.Search(IQuery,IFilter,int)"></see> instead.
		/// @throws BooleanQuery.TooManyClauses
		///</summary>
		ITopDocs Search(IWeight weight, IFilter filter, int n);

		///<summary>
		/// Returns the stored fields of document <code>i</code>.
		/// <see cref="IIndexReader.Document(int)"></see>
		///</summary>
		/// <exception cref="CorruptIndexException"> if the index is corrupt</exception>
		/// <exception cref="IOException">if there is a low-level IO error</exception>
		IDocument Doc(int i);

		///<summary>
		/// Get the <see cref="IDocument"></see> at the <code>n</code><sup>th</sup> position. The <see cref="IFieldSelector"></see>
		/// may be used to determine what <see cref="IField"></see>s to load and how they should be loaded.
		/// 
		/// <b>NOTE:</b> If the underlying Reader (more specifically, the underlying <code>FieldsReader</code>) is closed before the lazy <see cref="IField"></see> is
		/// loaded an exception may be thrown.  If you want the value of a lazy <see cref="IField"></see> to be available after closing you must
		/// explicitly load it or fetch the Document again with a new loader.
		///<param name="n">Get the document at the <code>n</code><sup>th</sup> position</param>
		/// <param name="fieldSelector">The <see cref="IFieldSelector"></see> to use to determine what Fields should be loaded on the Document.  May be null, in which case all Fields will be loaded.</param>
		///</summary>
		///<returns>
		///The stored fields of the <see cref="IDocument"></see> at the nth position
		///</returns>
		///<exception cref="CorruptIndexException"></exception>
		///<exception cref="IOException"></exception>
		IDocument Doc(int n, IFieldSelector fieldSelector);

		///<summary>
		/// Expert: called to re-write queries into primitive queries.
		///</summary>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		IQuery Rewrite(IQuery query);

		///<summary>
		/// Expert: low-level implementation method
		/// Returns an Explanation that describes how <code>doc</code> scored against
		/// <code>weight</code>.
		///
		/// <p>This is intended to be used in developing Similarity implementations,
		/// and, for good performance, should not be displayed with every hit.
		/// Computing an explanation is as expensive as executing the query over the
		/// entire index.
		/// </p>
		/// Applications should call <see cref="ISearcher.Explain(IQuery, int)"></see>.
		///</summary>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		IExplanation Explain(IWeight weight, int doc);

		///<summary>
		/////// Expert: Low-level search implementation with arbitrary sorting.  Finds
		/// the top <code>n</code> hits for <code>query</code>, applying
		/// <code>filter</code> if non-null, and sorting the hits by the criteria in
		/// <code>sort</code>.
		/// Applications should usually call <see cref="ISearcher.Search(IQuery,IFilter,int,ISort)"></see> instead.
		///</summary>
		///<exception cref="BooleanQuery.TooManyClauses"></exception>
		ITopFieldDocs Search(IWeight weight, IFilter filter, int n, ISort sort);
	}
}